package cn.zhoushengdao.bingwallpaper

import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.net.URL
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.concurrent.TimeUnit

val LocaleToTimezone = mapOf(
    "de-DE" to "Europe/Berlin",
    "en-CA" to "America/Toronto",
    "en-GB" to "Europe/London",
    "en-IN" to "Asia/Kolkata",
    "en-US" to "America/Los_Angeles",
    "es-ES" to "Europe/Madrid",
    "fr-CA" to "America/Toronto",
    "fr-FR" to "Europe/Paris",
    "it-IT" to "Europe/Rome",
    "ja-JP" to "Asia/Tokyo",
    "pt-BR" to "America/Sao_Paulo",
    "zh-CN" to "Asia/Shanghai"
)

class WallpaperRepository(
    private val context: Context, private val data: AppData
) {
    suspend fun fetchWallpapers(): List<WallpaperData> {
        return withContext(Dispatchers.IO) {
            val locale = data.currentLocale.first()
            val url = "https://services.bingapis.com/ge-apps/api/v2/bwc/hpimages?mkt=$locale"
            val json = URL(url).readText()
            val images = JSONObject(json).getJSONArray("images")

            List(images.length()) { i ->
                val image = images.getJSONObject(i)
                val mapLink = image.optJSONObject("mapLink")

                @Suppress("SpellCheckingInspection") WallpaperData(
                    date = getLocalDate(image.getString("fullstartdate"), locale),
                    imageUrl = image.getString("urlbase"),
                    copyright = image.getString("copyrighttext"),
                    searchUrl = image.getString("copyrightlink"),
                    title = image.getString("title"),
                    description = image.getString("description"),
                    headline = image.getString("headline"),
                    quizUrl = image.getString("quiz"),
                    mapImage = mapLink?.optString("Url", "") ?: "",
                    mapUrl = mapLink?.optString("Link", "") ?: "",
                )
            }
        }
    }

    private fun getLocalDate(time: String, locale: String): String {
        val utcDateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyyMMddHHmm"))
            .atOffset(ZoneOffset.UTC).toLocalDateTime()
        val zone = LocaleToTimezone[locale] ?: "Asia/Shanghai"
        return utcDateTime.atOffset(ZoneOffset.UTC).atZoneSameInstant(ZoneId.of(zone))
            .format(DateTimeFormatter.ISO_LOCAL_DATE)
    }

    suspend fun scheduleDailyUpdate() {
        val timeZone = LocaleToTimezone[data.currentLocale.first()] ?: "Asia/Shanghai"
        val nextUpdate = calculateNextUpdateTime(timeZone)

        val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true).build()

        val updateRequest = OneTimeWorkRequestBuilder<WallpaperUpdateWorker>().setInitialDelay(
            calculateDelay(nextUpdate), TimeUnit.MILLISECONDS
        ).setConstraints(constraints).addTag("daily_wallpaper_update").build()

        WorkManager.getInstance(context).enqueueUniqueWork(
            "WallpaperDailyUpdate", ExistingWorkPolicy.REPLACE, updateRequest
        )

    }

    private fun calculateNextUpdateTime(timeZone: String): ZonedDateTime {
        val zoneId = ZoneId.of(timeZone)
        return ZonedDateTime.now(zoneId).plusDays(1).withHour(0).withMinute(0).withSecond(0)
            .withNano(0)
    }

    private fun calculateDelay(nextUpdate: ZonedDateTime): Long {
        val now = Instant.now()
        return nextUpdate.toInstant().toEpochMilli() - now.toEpochMilli()
    }
}